//	--------------------------------------------------------------------
//	Copyright(C) 2006,2007 Zhao Yukun. All rights reserved.
//	This file is a part of the Xeres system.
//	Xeres 2007
//	Contact : xeres.engine@gmail.com
//	$(reservedInfo)
//	$(reservedDeclaration)
//	--------------------------------------------------------------------
///	@file	<XEditorContainer.h>
///	@path	~/src/editor/wm/
///	@date	2008/10/24
///	@brief	.

#pragma once

#include "editor/editor.h"

namespace xeres {

	/*! 
		\class	XEditorContainer
		\brief
	*/
	class XEditorContainer : public CWindowImpl< XEditorContainer >
	{
	public:
		DECLARE_WND_CLASS( _T("xeres__XEditorContainer") )

		/// \ctor
		XEditorContainer( void ) {
		}
		/// \dtor
		~XEditorContainer( void ) {
		}

		BOOL PreTranslateMessage(MSG* pMsg)
		{
			UNREFERENCED_PARAMETER( pMsg );
			return FALSE;
		}

		BEGIN_MSG_MAP(XEditorContainer)
			MESSAGE_HANDLER(WM_ACTIVATE , OnActivate)
			MESSAGE_HANDLER(WM_CREATE, OnCreate)
			MESSAGE_HANDLER(WM_PAINT , OnPaint)
			MESSAGE_HANDLER(WM_SIZE , OnSize)
			MESSAGE_HANDLER(WM_ERASEBKGND , OnEraseBkgnd)
		END_MSG_MAP()

		LRESULT OnActivate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) {
			// Dummy filter to refresh dispatcher states.
			return S_OK;
		}
		LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) {
			return S_OK;
		}
		LRESULT OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) {
			CPaintDC dc( m_hWnd );
			return S_OK;
		}
		LRESULT OnSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled ) {
			// resize container
			ArrangeSubs();
			bHandled = FALSE;
			return S_OK;
		}
		LRESULT OnEraseBkgnd(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) {
			return S_OK;
		}

		// Set sub windows
		void SetSubsRow( int row )
		{
			m_subs.resize( row );

			CRect rect;
			GetClientRect( &rect );
			int height = rect.Height();
			float h = 1 / float(row);

			// average row width , height
			for( size_t r = 0 , totalr = m_subs.size() ; r < totalr ; ++r )
			{
				_SubRow& row = m_subs[r];
				row.percent = h;
			}
		}

		// Set row windows count
		void SetSubCol( int rowIndex , int col )
		{
			XS_ASSERT( rowIndex >= 0 && rowIndex < (int)m_subs.size() );
			_SubRow& row = m_subs[rowIndex];
			row.row.resize( col );
			
			CRect rect;
			GetClientRect( &rect );

			int width = rect.Width();
			float w = 1 / float(col);

			// average row width
			for( size_t c = 0 , totalc = row.row.size() ; c < totalc ; ++c )
			{
				_SubWindow& win = row.row[c];
				win.percent = w;
			}
		}

		// Set window.
		CWindow * SetSub( int rowIndex , int colIndex , CWindow * sub , int absWidth , float relativeWidth )
		{
			XS_ASSERT( rowIndex >= 0 && rowIndex < (int)m_subs.size() );
			_SubRow& row = m_subs[rowIndex];
			XS_ASSERT( colIndex >= 0 && colIndex < (int)row.row.size() );
			_SubWindow& win = row.row[colIndex];
			
			CWindow * org = win.sub_window;

			if( org )
			{
				org->SetParent( NULL );
				DWORD style = org->GetWindowLong( GWL_STYLE );
				org->SetWindowLong( GWL_STYLE , style & ~ (WS_CHILD | WS_VISIBLE) );
			}
			win.sub_window = sub;
			win.absolute = absWidth;
			win.percent = relativeWidth;
			return org;
		}

		/// \brief	Arrange subs.
		void ArrangeSubs( void )
		{
			// Get window rect.
			CRect rect;
			GetClientRect( &rect );
			int width = rect.Width();
			int height = rect.Height();

			// For each row.
			// Assume that row height & window width percentage is adjusted sum to 1.

			int starty = 0;
			for( size_t r = 0 , totalr = m_subs.size() ; r < totalr ; ++r )
			{
				_SubRow& row = m_subs[r];
				int h = row.absolute < 0 ? int( height * row.percent ) : row.absolute;

				int startx = 0;
				for( size_t c = 0 , totalc = m_subs.size() ; c < totalc ; ++c )
				{
					_SubWindow& win = row.row[c];
					int w = win.absolute < 0 ? int( width * win.percent ) : win.absolute;

					if( win.sub_window )
					{
						win.sub_window->SetParent( m_hWnd );
						DWORD style = win.sub_window->GetWindowLong( GWL_STYLE );
						win.sub_window->SetWindowLong( GWL_STYLE , WS_CHILD | WS_VISIBLE | style );
						win.sub_window->SetWindowPos( NULL , startx , starty , startx + w , starty + h , SWP_SHOWWINDOW );
					}

					startx += w;
				}
				starty += h;
			}
		}

	private:

		//@ data

		struct _SubWindow
		{
			// window
			CWindow *			sub_window;
			float				percent;
			int					absolute;

			// ctor
			_SubWindow( void ) : sub_window( NULL ) , percent( 0 ) , absolute(-1) {}
		};

		struct _SubRow
		{
			// windows in the row
			std::vector<_SubWindow> row;
			float				percent;
			int					absolute;

			// ctor
			_SubRow( void ) : percent( 0 ) , absolute(-1)
			{
				row.resize(1);
			}
		};

		// sub windows
		std::vector< _SubRow >	m_subs;
		
	};

} // namespace xeres
